package com.example.nfc.server.utils.task;


import java.util.ArrayList;
import java.util.List;

/**
 * Create by 游德禄 on 2019-10-30
 *  异步任务栈
 *  用法：
 *       Task task = Task.getInstance();
 *         task.then(new Task.Action() {
 *             @Override
 *             public Object run(Object... obj) {
 *                 try {
 *                     Thread.sleep(2000);
 *                 }catch(InterruptedException e){
 *                     e.printStackTrace();
 *                 }
 *                 return gson.toJson(obj);
 *             }
 *         }, 1,23423423,423423,3).then(new Task.Action() {
 *             @Override
 *             public Object run(Object... obj) {
 *                 try {
 *                     Thread.sleep(2000);
 *                 }catch(InterruptedException e){
 *                     e.printStackTrace();
 *                 }
 *                 return gson.toJson(obj);
 *             }
 *         },99,234,234,234,234,234,2,34,23,4).then(new Task.Action() {
 *             @Override
 *             public Object run(Object... obj) {
 *                 for(int i = 0 ; i < 100 ;i++) {
 *                     try {
 *                         Thread.sleep(1000);
 *                         Task.onProgress(i);
 *                     } catch (InterruptedException e) {
 *                         e.printStackTrace();
 *                     }
 *                 }
 *                 return gson.toJson(obj);
 *             }
 *         },34,43,3,3).start(new Task.Listener() {
 *             @Override
 *             public void started(int step) {
 *                 NLog.e("Task","started",step);
 *             }
 *
 *             @Override
 *             public void finish(int step, Object obj) {
 *                 NLog.e("Task","finish",step,gson.toJson(obj));
 *             }
 *
 *             @Override
 *             public void progress(int step, Integer... integers) {
 *                 NLog.e("Task","progress",step,integers[0]);
 *             }
 *
 *             @Override
 *             public void allFinish(int threadCount) {
 *                 NLog.e("Task","allFinish",threadCount);
 *             }
 *         });
 *
 *         //如果不用监听结果，直接start();
 *         task.start();
 *      //如果线程运行时间过长，要在结束时取消
 *     @Override
 *     protected void onDestroy() {
 *         super.onDestroy();
 *         Task.getInstance().cancel();
 *     }
 *
 */
public class Task implements OnFinish {
    private static Task instance;
    private List<Runable> runableList ;
    private List<Runable> tempList;
    private Listener listener;
    private int step ;
    private long startTime = 0;
    public static Task getInstance() {
        if (instance == null) {
            synchronized (Task.class) {
                if (instance == null) {
                    instance = new Task();
                }
            }
        }
        return instance;
    }
    public Task then(Action action, Object...obj){
        if(tempList==null){
            tempList = new ArrayList<>();
        }
        tempList.add(new Runable(action,obj));
        return this;
    }

    /**
     * 进度
     * @param integers
     */
    public static void onProgress(Integer...integers){
        if(getInstance().listener!=null){
            getInstance().listener.progress(getInstance().step,integers);
        }
    }

    /**
     * 强制设置当前步骤的ID
     * @param threadId
     */
    public static void setThreadId(int threadId){
        getInstance().runableList.get(getInstance().step).stepId = threadId;
    }

    /**
     * 启动
     */
    public void start(){
        start(null);
    }

    /**
     * 启动
     * @param listener
     */
    public boolean start(Listener listener){
        if(tempList==null||tempList.size()==0){
            return false;
        }
        cancel();
        runableList = new ArrayList<>(tempList);
        tempList =null;
        startTime = System.currentTimeMillis();
        if(listener!=null) {
            this.listener = listener;
        }
        step = 0 ;
        next();
        return true;
    }
    private void next(){
        runableList.get(step).start(step,listener,this);
    }
    //在onDestroy调一下这个方法
    public void cancel(){
        if(runableList==null){
            return;
        }
        if(runableList.size()==0){
            return;
        }
        for(int i = 0 ; i < runableList.size();i++){
            if(!runableList.get(i).isCancelled()){
                runableList.get(i).cancel(true);
            }
        }
        step = 0 ;
        runableList = null;
    }
    public interface Action{
        Object run(Object... obj) throws Exception;
    }

    @Override
    public void onfinish() {
        step++;
        if(step==runableList.size()){
            long endTime = System.currentTimeMillis() - startTime;
            if(listener!=null) {
                listener.allFinish(step,endTime);
            }
            step = 0 ;
            runableList.clear();
        }else{
            next();
        }
    }

    /**
     * 监听事件
     */
    public interface Listener{
        void started(int step);
        void finish(int step, boolean isOk, Object result);
        void progress(int step, Integer... integers);
        void allFinish(int threadCount, long timeMillis);
    }
    public void distory(){
        instance = null;
    }
}
